bitkeeper revision 1.1159.170.78 (41d829e8lHqACg7gEEHdWaU-Jb1YdQ)
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Sun, 2 Jan 2005 17:05:44 +0000 (17:05 +0000)
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Sun, 2 Jan 2005 17:05:44 +0000 (17:05 +0000)
Network driver fixes.

linux-2.6.10-xen-sparse/drivers/xen/netback/common.h
linux-2.6.10-xen-sparse/drivers/xen/netback/interface.c
linux-2.6.10-xen-sparse/drivers/xen/netback/netback.c
linux-2.6.10-xen-sparse/drivers/xen/netfront/netfront.c
tools/examples/vif-bridge

index a8eeac8aacded9ee77e7576dba58ce259149c4ab..0831cbe311a5b450234048ba5464f869ffa75941 100644 (file)
@@ -59,6 +59,7 @@ typedef struct netif_st {
 
     /* Miscellaneous private stuff. */
     enum { DISCONNECTED, DISCONNECTING, CONNECTED } status;
+    int active;
     /*
      * DISCONNECT response is deferred until pending requests are ack'ed.
      * We therefore need to store the id from the original request.
@@ -67,7 +68,6 @@ typedef struct netif_st {
     struct netif_st *hash_next;
     struct list_head list;  /* scheduling list */
     atomic_t         refcnt;
-    spinlock_t       rx_lock, tx_lock;
     struct net_device *dev;
     struct net_device_stats stats;
 
@@ -90,7 +90,8 @@ netif_t *netif_find_by_handle(domid_t domid, unsigned int handle);
 void netif_interface_init(void);
 void netif_ctrlif_init(void);
 
-void netif_deschedule(netif_t *netif);
+void netif_schedule_work(netif_t *netif);
+void netif_deschedule_work(netif_t *netif);
 
 int netif_be_start_xmit(struct sk_buff *skb, struct net_device *dev);
 struct net_device_stats *netif_be_get_stats(struct net_device *dev);
index 8de03f644b351fff8b59eabd29774d8e043ea35c..9a3eea5932059cf3b74ff6c74ae9f3edf0fcbcf2 100644 (file)
@@ -27,6 +27,44 @@ netif_t *netif_find_by_handle(domid_t domid, unsigned int handle)
     return netif;
 }
 
+static void __netif_up(netif_t *netif)
+{
+    struct net_device *dev = netif->dev;
+    spin_lock_bh(&dev->xmit_lock);
+    netif->active = 1;
+    spin_unlock_bh(&dev->xmit_lock);
+    (void)request_irq(netif->irq, netif_be_int, 0, dev->name, netif);
+    netif_schedule_work(netif);
+}
+
+static void __netif_down(netif_t *netif)
+{
+    struct net_device *dev = netif->dev;
+    spin_lock_bh(&dev->xmit_lock);
+    netif->active = 0;
+    spin_unlock_bh(&dev->xmit_lock);
+    free_irq(netif->irq, netif);
+    netif_deschedule_work(netif);
+}
+
+static int net_open(struct net_device *dev)
+{
+    netif_t *netif = netdev_priv(dev);
+    if ( netif->status == CONNECTED )
+        __netif_up(netif);
+    netif_start_queue(dev);
+    return 0;
+}
+
+static int net_close(struct net_device *dev)
+{
+    netif_t *netif = netdev_priv(dev);
+    netif_stop_queue(dev);
+    if ( netif->status == CONNECTED )
+        __netif_down(netif);
+    return 0;
+}
+
 static void __netif_disconnect_complete(void *arg)
 {
     netif_t              *netif = (netif_t *)arg;
@@ -40,9 +78,6 @@ static void __netif_disconnect_complete(void *arg)
      */
     unbind_evtchn_from_irq(netif->evtchn);
     vfree(netif->tx); /* Frees netif->rx as well. */
-    rtnl_lock();
-    (void)dev_close(netif->dev);
-    rtnl_unlock();
 
     /* Construct the deferred response message. */
     cmsg.type         = CMSG_NETIF_BE;
@@ -95,13 +130,11 @@ void netif_create(netif_be_create_t *create)
         return;
     }
 
-    netif = dev->priv;
+    netif = netdev_priv(dev);
     memset(netif, 0, sizeof(*netif));
     netif->domid  = domid;
     netif->handle = handle;
     netif->status = DISCONNECTED;
-    spin_lock_init(&netif->rx_lock);
-    spin_lock_init(&netif->tx_lock);
     atomic_set(&netif->refcnt, 0);
     netif->dev = dev;
 
@@ -124,6 +157,8 @@ void netif_create(netif_be_create_t *create)
 
     dev->hard_start_xmit = netif_be_start_xmit;
     dev->get_stats       = netif_be_get_stats;
+    dev->open            = net_open;
+    dev->stop            = net_close;
 
     /* Disable queuing. */
     dev->tx_queue_len = 0;
@@ -136,7 +171,11 @@ void netif_create(netif_be_create_t *create)
     memset(dev->dev_addr, 0xFF, ETH_ALEN);
     dev->dev_addr[0] &= ~0x01;
 
-    if ( (err = register_netdev(dev)) != 0 )
+    rtnl_lock();
+    err = register_netdevice(dev);
+    rtnl_unlock();
+
+    if ( err != 0 )
     {
         DPRINTK("Could not register new net device %s: err=%d\n",
                 dev->name, err);
@@ -249,18 +288,17 @@ void netif_connect(netif_be_connect_t *connect)
         (netif_tx_interface_t *)vma->addr;
     netif->rx             = 
         (netif_rx_interface_t *)((char *)vma->addr + PAGE_SIZE);
-    netif->status         = CONNECTED;
-    netif_get(netif);
-
     netif->tx->resp_prod = netif->rx->resp_prod = 0;
+    netif_get(netif);
+    wmb(); /* Other CPUs see new state before interface is started. */
 
     rtnl_lock();
-    (void)dev_open(netif->dev);
+    netif->status = CONNECTED;
+    wmb();
+    if ( netif_running(netif->dev) )
+        __netif_up(netif);
     rtnl_unlock();
 
-    (void)request_irq(netif->irq, netif_be_int, 0, netif->dev->name, netif);
-    netif_start_queue(netif->dev);
-
     connect->status = NETIF_BE_STATUS_OKAY;
 }
 
@@ -281,12 +319,13 @@ int netif_disconnect(netif_be_disconnect_t *disconnect, u8 rsp_id)
 
     if ( netif->status == CONNECTED )
     {
+        rtnl_lock();
         netif->status = DISCONNECTING;
         netif->disconnect_rspid = rsp_id;
-        wmb(); /* Let other CPUs see the status change. */
-        netif_stop_queue(netif->dev);
-        free_irq(netif->irq, netif);
-        netif_deschedule(netif);
+        wmb();
+        if ( netif_running(netif->dev) )
+            __netif_down(netif);
+        rtnl_unlock();
         netif_put(netif);
         return 0; /* Caller should not send response message. */
     }
index 41d947bacfbc1204e575fccfd0901276365f3a58..d45b0c3f59f503e2a49ee2342f4b193ebaeea483 100644 (file)
@@ -58,7 +58,6 @@ static PEND_RING_IDX pending_prod, pending_cons;
 
 /* Freed TX SKBs get batched on this ring before return to pending_ring. */
 static u16 dealloc_ring[MAX_PENDING_REQS];
-static spinlock_t dealloc_lock = SPIN_LOCK_UNLOCKED;
 static PEND_RING_IDX dealloc_prod, dealloc_cons;
 
 static struct sk_buff_head tx_queue;
@@ -122,12 +121,13 @@ static inline int is_xen_skb(struct sk_buff *skb)
 
 int netif_be_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-    netif_t *netif = (netif_t *)dev->priv;
+    netif_t *netif = netdev_priv(dev);
 
     ASSERT(skb->dev == dev);
 
     /* Drop the packet if the target domain has no receive buffers. */
-    if ( (netif->rx_req_cons == netif->rx->req_prod) ||
+    if ( !netif->active || 
+         (netif->rx_req_cons == netif->rx->req_prod) ||
          ((netif->rx_req_cons-netif->rx_resp_prod) == NETIF_RX_RING_SIZE) )
         goto drop;
 
@@ -153,6 +153,7 @@ int netif_be_start_xmit(struct sk_buff *skb, struct net_device *dev)
     }
 
     netif->rx_req_cons++;
+    netif_get(netif);
 
     skb_queue_tail(&rx_queue, skb);
     tasklet_schedule(&net_rx_tasklet);
@@ -203,7 +204,7 @@ static void net_rx_action(unsigned long unused)
     mmu = rx_mmu;
     while ( (skb = skb_dequeue(&rx_queue)) != NULL )
     {
-        netif   = (netif_t *)skb->dev->priv;
+        netif   = netdev_priv(skb->dev);
         vdata   = (unsigned long)skb->data;
         mdata   = virt_to_machine(vdata);
 
@@ -213,6 +214,7 @@ static void net_rx_action(unsigned long unused)
             if ( net_ratelimit() )
                 printk(KERN_WARNING "Memory squeeze in netback driver.\n");
             mod_timer(&net_timer, jiffies + HZ);
+            skb_queue_head(&rx_queue, skb);
             break;
         }
 
@@ -260,7 +262,7 @@ static void net_rx_action(unsigned long unused)
     mmu = rx_mmu;
     while ( (skb = __skb_dequeue(&rxq)) != NULL )
     {
-        netif   = (netif_t *)skb->dev->priv;
+        netif   = netdev_priv(skb->dev);
         size    = skb->tail - skb->data;
 
         /* Rederive the machine addresses. */
@@ -297,6 +299,7 @@ static void net_rx_action(unsigned long unused)
             notify_list[notify_nr++] = evtchn;
         }
 
+        netif_put(netif);
         dev_kfree_skb(skb);
 
         mcl += 2;
@@ -326,7 +329,7 @@ static void net_alarm(unsigned long unused)
 
 struct net_device_stats *netif_be_get_stats(struct net_device *dev)
 {
-    netif_t *netif = dev->priv;
+    netif_t *netif = netdev_priv(dev);
     return &netif->stats;
 }
 
@@ -353,7 +356,7 @@ static void add_to_net_schedule_list_tail(netif_t *netif)
         return;
 
     spin_lock_irq(&net_schedule_list_lock);
-    if ( !__on_net_schedule_list(netif) && (netif->status == CONNECTED) )
+    if ( !__on_net_schedule_list(netif) && netif->active )
     {
         list_add_tail(&netif->list, &net_schedule_list);
         netif_get(netif);
@@ -361,7 +364,7 @@ static void add_to_net_schedule_list_tail(netif_t *netif)
     spin_unlock_irq(&net_schedule_list_lock);
 }
 
-static inline void netif_schedule_work(netif_t *netif)
+void netif_schedule_work(netif_t *netif)
 {
     if ( (netif->tx_req_cons != netif->tx->req_prod) &&
          ((netif->tx_req_cons-netif->tx_resp_prod) != NETIF_TX_RING_SIZE) )
@@ -371,7 +374,7 @@ static inline void netif_schedule_work(netif_t *netif)
     }
 }
 
-void netif_deschedule(netif_t *netif)
+void netif_deschedule_work(netif_t *netif)
 {
     remove_from_net_schedule_list(netif);
 }
@@ -426,10 +429,8 @@ static void net_tx_action(unsigned long unused)
 
         netif = pending_tx_info[pending_idx].netif;
 
-        spin_lock(&netif->tx_lock);
         make_tx_response(netif, pending_tx_info[pending_idx].req.id, 
                          NETIF_RSP_OKAY);
-        spin_unlock(&netif->tx_lock);
         
         pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx;
 
@@ -630,11 +631,12 @@ static void net_tx_action(unsigned long unused)
 
 static void netif_idx_release(u16 pending_idx)
 {
+    static spinlock_t _lock = SPIN_LOCK_UNLOCKED;
     unsigned long flags;
 
-    spin_lock_irqsave(&dealloc_lock, flags);
+    spin_lock_irqsave(&_lock, flags);
     dealloc_ring[MASK_PEND_IDX(dealloc_prod++)] = pending_idx;
-    spin_unlock_irqrestore(&dealloc_lock, flags);
+    spin_unlock_irqrestore(&_lock, flags);
 
     tasklet_schedule(&net_tx_tasklet);
 }
@@ -657,46 +659,6 @@ static void netif_skb_release(struct sk_buff *skb)
     netif_idx_release(pending_idx);
 }
 
-#if 0
-long flush_bufs_for_netif(netif_t *netif)
-{
-    NETIF_RING_IDX i;
-
-    /* Return any outstanding receive buffers to the guest OS. */
-    spin_lock(&netif->rx_lock);
-    for ( i = netif->rx_req_cons; 
-          (i != netif->rx->req_prod) &&
-              ((i-netif->rx_resp_prod) != NETIF_RX_RING_SIZE);
-          i++ )
-    {
-        make_rx_response(netif,
-                         netif->rx->ring[MASK_NETIF_RX_IDX(i)].req.id,
-                         NETIF_RSP_DROPPED, 0, 0);
-    }
-    netif->rx_req_cons = i;
-    spin_unlock(&netif->rx_lock);
-
-    /*
-     * Flush pending transmit buffers. The guest may still have to wait for
-     * buffers that are queued at a physical NIC.
-     */
-    spin_lock(&netif->tx_lock);
-    for ( i = netif->tx_req_cons; 
-          (i != netif->tx->req_prod) &&
-              ((i-netif->tx_resp_prod) != NETIF_TX_RING_SIZE);
-          i++ )
-    {
-        make_tx_response(netif,
-                         netif->tx->ring[MASK_NETIF_TX_IDX(i)].req.id,
-                         NETIF_RSP_DROPPED);
-    }
-    netif->tx_req_cons = i;
-    spin_unlock(&netif->tx_lock);
-
-    return 0;
-}
-#endif
-
 irqreturn_t netif_be_int(int irq, void *dev_id, struct pt_regs *regs)
 {
     netif_t *netif = dev_id;
index d2b96cbe0f1cae2b5d483ff736772eebcdf17b3e..01bea1e6fc0e5a45fcb915aeb3a7b1532668ab4f 100644 (file)
@@ -277,7 +277,7 @@ static int vif_wake(struct net_device *dev)
 
 static int network_open(struct net_device *dev)
 {
-    struct net_private *np = dev->priv;
+    struct net_private *np = netdev_priv(dev);
 
     memset(&np->stats, 0, sizeof(np->stats));
 
@@ -295,7 +295,7 @@ static void network_tx_buf_gc(struct net_device *dev)
 {
     NETIF_RING_IDX i, prod;
     unsigned short id;
-    struct net_private *np = dev->priv;
+    struct net_private *np = netdev_priv(dev);
     struct sk_buff *skb;
 
     if ( np->backend_state != BEST_CONNECTED )
@@ -342,7 +342,7 @@ static void network_tx_buf_gc(struct net_device *dev)
 static void network_alloc_rx_buffers(struct net_device *dev)
 {
     unsigned short id;
-    struct net_private *np = dev->priv;
+    struct net_private *np = netdev_priv(dev);
     struct sk_buff *skb;
     int i, batch_target;
     NETIF_RING_IDX req_prod = np->rx->req_prod;
@@ -433,7 +433,7 @@ static void network_alloc_rx_buffers(struct net_device *dev)
 static int network_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
     unsigned short id;
-    struct net_private *np = (struct net_private *)dev->priv;
+    struct net_private *np = netdev_priv(dev);
     netif_tx_request_t *tx;
     NETIF_RING_IDX i;
 
@@ -509,7 +509,7 @@ static int network_start_xmit(struct sk_buff *skb, struct net_device *dev)
 static irqreturn_t netif_int(int irq, void *dev_id, struct pt_regs *ptregs)
 {
     struct net_device *dev = dev_id;
-    struct net_private *np = dev->priv;
+    struct net_private *np = netdev_priv(dev);
     unsigned long flags;
 
     spin_lock_irqsave(&np->tx_lock, flags);
@@ -526,7 +526,7 @@ static irqreturn_t netif_int(int irq, void *dev_id, struct pt_regs *ptregs)
 
 static int netif_poll(struct net_device *dev, int *pbudget)
 {
-    struct net_private *np = dev->priv;
+    struct net_private *np = netdev_priv(dev);
     struct sk_buff *skb, *nskb;
     netif_rx_response_t *rx;
     NETIF_RING_IDX i, rp;
@@ -704,7 +704,7 @@ static int netif_poll(struct net_device *dev, int *pbudget)
 
 static int network_close(struct net_device *dev)
 {
-    struct net_private *np = dev->priv;
+    struct net_private *np = netdev_priv(dev);
     np->user_state = UST_CLOSED;
     netif_stop_queue(np->dev);
     return 0;
@@ -713,7 +713,7 @@ static int network_close(struct net_device *dev)
 
 static struct net_device_stats *network_get_stats(struct net_device *dev)
 {
-    struct net_private *np = (struct net_private *)dev->priv;
+    struct net_private *np = netdev_priv(dev);
     return &np->stats;
 }
 
@@ -725,7 +725,7 @@ static void network_connect(struct net_device *dev,
     int i, requeue_idx;
     netif_tx_request_t *tx;
 
-    np = dev->priv;
+    np = netdev_priv(dev);
     spin_lock_irq(&np->tx_lock);
     spin_lock(&np->rx_lock);
 
@@ -889,7 +889,8 @@ static void vif_close(struct net_private *np)
  * Allocates tx/rx pages.
  * Sends connect message to xend.
  */
-static void vif_disconnect(struct net_private *np){
+static void vif_disconnect(struct net_private *np)
+{
     DPRINTK(">\n");
     if(np->tx) free_page((unsigned long)np->tx);
     if(np->rx) free_page((unsigned long)np->rx);
@@ -967,7 +968,7 @@ static int create_netdev(int handle, struct net_device **val)
         goto exit;
     }
 
-    np                = dev->priv;
+    np                = netdev_priv(dev);
     np->backend_state = BEST_CLOSED;
     np->user_state    = UST_CLOSED;
     np->handle        = handle;
@@ -1046,7 +1047,7 @@ target_vif(
 
   exit:
     if ( np != NULL )
-        *np = ((dev && !err) ? dev->priv : NULL);
+        *np = ((dev && !err) ? netdev_priv(dev) : NULL);
     DPRINTK("< err=%d\n", err);
     return err;
 }
index 505ac1ec51c332aec55da8bd6ec90492d992e86a..42bdf0e17344223b63bb34e55cab87f4ba81533f 100755 (executable)
@@ -76,6 +76,7 @@ fi
 
 # Add/remove vif to/from bridge.
 brctl ${brcmd} ${bridge} ${vif}
+ifconfig ${vif} $OP
 
 if [ ${ip} ] ; then